﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Shine.Util.Security
{
    /// <summary>
    /// 概述：提供高级加密标准 (AES) 对称算法的加密和解密实现<br />
    /// </summary>
    public class AesCryptography
    {
        /// <summary>
        /// 密码。
        /// </summary>
        private static string Password = "Undefined";

        /// <summary>
        /// 密钥。
        /// </summary>
        private static string Salt = "Undefined";

        /// <summary>
        /// 加密字节数组到文本。
        /// </summary>
        /// <param name="bytes">需要加密的字节数组。</param>
        /// <returns>加密得到的文本。</returns>
        public static string Encrypt(byte[] bytes)
        {
            return Encrypt(bytes, "", "");
        }

        /// <summary>
        /// 加密字节数组到文本。
        /// </summary>
        /// <param name="bytes">需要加密的字节数组。</param>
        /// <param name="password">密码。</param>
        /// <param name="salt">密钥。</param>
        /// <returns>加密得到的文本。</returns>
        public static string Encrypt(byte[] bytes, string password, string salt)
        {
            if (bytes == null)
            {
                return null;
            }

            if (string.IsNullOrEmpty(password))
            {
                password = Password;
            }

            if (string.IsNullOrEmpty(salt))
            {
                salt = Salt;
            }

            Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(Password, Encoding.UTF8.GetBytes(salt));

            AesManaged aes = new AesManaged();
            aes.Key = rfc.GetBytes(aes.KeySize / 8);
            aes.IV = rfc.GetBytes(aes.BlockSize / 8);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
                cryptoStream.Write(bytes, 0, bytes.Length);
                cryptoStream.Close();

                return Convert.ToBase64String(memoryStream.ToArray());
            }
        }

        /// <summary>
        /// 解密文本到字节数组。
        /// </summary>
        /// <param name="encryptedString">需要解密的文本。</param>
        /// <returns>解密得到的字节数组。</returns>
        public static byte[] Decrypt(string encryptedString)
        {
            return Decrypt(encryptedString, "", "");
        }

        /// <summary>
        /// 解密文本到字节数组。
        /// </summary>
        /// <param name="encryptedString">需要解密的文本。</param>
        /// <param name="password">密码。</param>
        /// <param name="salt">密钥。</param>
        /// <returns>解密得到的字节数组。</returns>
        public static byte[] Decrypt(string encryptedString, string password, string salt)
        {
            if (string.IsNullOrEmpty(encryptedString))
            {
                return null;
            }

            if (string.IsNullOrEmpty(password))
            {
                password = Password;
            }

            if (string.IsNullOrEmpty(salt))
            {
                salt = Salt;
            }

            Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(Password, Encoding.UTF8.GetBytes(salt));

            AesManaged aes = new AesManaged();
            aes.Key = rfc.GetBytes(aes.KeySize / 8);
            aes.IV = rfc.GetBytes(aes.BlockSize / 8);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write);
                byte[] encryptedBytes = Convert.FromBase64String(encryptedString);
                cryptoStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                cryptoStream.Close();

                return memoryStream.ToArray();
            }
        }
    }
}
